package core;

import static org.junit.Assert.*;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class ProductTests {

	@BeforeClass
	public static void setUpBeforeClass() throws Exception 
	{
	}

	@AfterClass
	public static void tearDownAfterClass() throws Exception 
	{
	}

	@Before
	public void setUp() throws Exception 
	{
	}

	@After
	public void tearDown() throws Exception 
	{
	}

	@Test(expected=IllegalArgumentException.class)
	public void testConstructorIllegalTime()
	{
		Calendar newDate = new GregorianCalendar();
		newDate.add(Calendar.MONTH, 2);
		
		//public Product(Date creationDate, Barcode barcode, 
        //String description, Amount amount, int shelfLife, 
        //int threeMonthSupply)throws IllegalArgumentException
		
		Product newProduct = new Product(newDate, new Barcode("123456789012"), "THIS IS A PRODUCT",
				new Amount(Unit.count, 1), 0, 0);
		fail("No argument Thrown");
	}

	@Test(expected=IllegalArgumentException.class)
	public void testConstructorIllegalDescription()
	{
		Calendar newDate = new GregorianCalendar();
		
		Product newProduct = new Product(newDate, new Barcode("123456789012"), "",
				new Amount(Unit.count, 1), 0, 0);
	}
	
	@Test(expected=IllegalArgumentException.class)
	public void testConstructorIllegalShelfLife()
	{
		Calendar newDate = new GregorianCalendar();
		
		Product newProduct = new Product(newDate, new Barcode("123456789012"), "A",
				new Amount(Unit.count, 1), -2, 0);
	}
	
	@Test(expected=IllegalArgumentException.class)
	public void testConstructorIllegal3MonthSupply()
	{
		Calendar newDate = new GregorianCalendar();
		
		Product newProduct = new Product(newDate, new Barcode("123456789012"), "A",
				new Amount(Unit.count, 1), 0, -1);
	}
	
	@Test
	public void testConstructorSuccess()
	{
		Calendar newDate = new GregorianCalendar();
		
		Product newProduct = new Product (newDate, new Barcode("123456789012"), "hellof",
				new Amount(Unit.count, 1), 10, 12);
		
		if (newProduct == null) fail("object not created.");
		if (newProduct.getAmount().getUnit() != Unit.count) fail("Object unit not correct");
		if (newProduct.getAmount().getSize() != 1) fail("Object size not correct");
		if (newProduct.getBarcodeString().compareTo("123456789012") != 0) 
			fail("Barcode not correct");
		if (newProduct.getBarcodeString().compareTo("1245") == 0) 
			fail("Control did not pass");
		if (newProduct.getDescription().compareTo("hellof") != 0) 
			fail("Description not the same");
		if (newProduct.getDescription().compareTo("hedllof") == 0) 
			fail("Control failed");
		if (newProduct.getCreationDate() != newDate) fail("Date not the same");
		if (newProduct.getShelfLife() != 10) fail("Selflife not correct");
		if (newProduct.getThreeMonthSupply() != 12) fail("3Monthsupply not correct");
		if (newProduct.getThreeMonthSupply() == 13) fail("control failed");
	}
	
	public Product setupAProductForTest()
	{
		Calendar createDate = new GregorianCalendar();
		
		Product newProduct = new Product (createDate, new Barcode("123456789012"), "hellof",
				new Amount(Unit.count, 1), 10, 12);
		return newProduct;
	}
	
	@Test
	public void testSetDate()
	{
		Product product = setupAProductForTest();
		
		Calendar createDate = product.getCreationDate();
		
		assertTrue(product.getCreationDate() == createDate);
		
		product.setCreationDate(new GregorianCalendar());
		
		assertTrue(product.getCreationDate() != createDate);
		if (product.getCreationDate().getTimeInMillis() < (createDate.getTimeInMillis()))
		{
			System.out.println(product.getCreationDate().getTimeInMillis() + " > " + 
		createDate.getTimeInMillis());
			fail("Something wrong in The < test");
		}
		
		Calendar newDate = new GregorianCalendar();
		newDate.add(Calendar.MONTH, -2);
		
		product.setCreationDate(newDate);
		
		assertFalse(product.getCreationDate().compareTo(createDate) > 0);
		assertTrue(product.getCreationDate().compareTo(createDate) < 0);
		
		try
		{
			newDate = new GregorianCalendar();
			newDate.add(Calendar.MONTH, 10);
			product.setCreationDate(newDate);
		}
		catch (IllegalArgumentException e)
		{
			System.out.println("Caught the expected Exception. SetCreationDate");
			return;
		}
		
		//if you get here then you fail
		fail("Didn't throw correct exception");
	}
	
	@Test(expected=IllegalArgumentException.class)
	public void testSetBarcode()
	{
		Product product = setupAProductForTest();
		
		product.setBarCode(null);
	}
	
	@Test
	public void testSetDescription()
	{
		Product product = setupAProductForTest();
		
		String oldDescription = product.getDescription();
		
		assertTrue(oldDescription.compareTo(product.getDescription()) == 0);
		
		product.setDescription("me");
		
		assertFalse(oldDescription.compareTo(product.getDescription()) == 0);
		assertTrue(oldDescription.compareTo(product.getDescription()) != 0);
		assertTrue(product.getDescription().compareTo("me") == 0);
		
		try
		{
			product.setDescription("");
		}
		catch(IllegalArgumentException e)
		{
			System.out.println("Caught the expected exception. setDescription.");
			return;
		}
		
		fail("Didn't catch correct Exception");
	}

	@Test(expected=IllegalArgumentException.class)
	public void testSetAmount()
	{
		Product product = setupAProductForTest();
		
		product.setBarCode(null);
	}
	
	@Test
	public void testSetShelfLife()
	{
		Product product = setupAProductForTest();
		
		int curShelfLife = product.getShelfLife();
		
		assertTrue(curShelfLife == product.getShelfLife());
		
		product.setShelfLife(123);
		
		assertFalse(curShelfLife == product.getShelfLife());
		assertTrue(curShelfLife != product.getShelfLife());
		assertTrue(product.getShelfLife() == 123);
		
		try
		{
			product.setShelfLife(-1);
		}
		catch(IllegalArgumentException e)
		{
			System.out.println("Caught the expected exception. setShelfLife.");
			return;
		}
		
		fail("Didn't catch correct Exception");
	}
	
	@Test
	public void testSet3MonthSupply()
	{
		Product product = setupAProductForTest();
		
		int cur3ms = product.getThreeMonthSupply();
		
		assertTrue(cur3ms == product.getThreeMonthSupply());
		
		product.setThreeMonthSupply(234);
		
		assertTrue(cur3ms != product.getThreeMonthSupply());
		assertFalse(cur3ms == product.getThreeMonthSupply());
		assertTrue(cur3ms != 234);
		assertTrue(product.getThreeMonthSupply() == 234);
		
		
		try
		{
			product.setThreeMonthSupply(-1);
		}
		catch(IllegalArgumentException e)
		{
			System.out.println("Caught the expected exception. setThreeMonthSupply.");
			return;
		}
		
		fail("Didn't catch correct Exception");
	}
	
	@Test
	public void testEquals()
	{
		Product p1 = setupAProductForTest();
		Product p2 = new Product (new GregorianCalendar(), new Barcode("123456789012"), "hellmesaof",
				new Amount(Unit.count, 13), 0, 2);
		Product p3 = new Product (new GregorianCalendar(), new Barcode("123456789013"), "goodmesaof",
				new Amount(Unit.count, 13), 0, 2);
		Product p4 = new Product (new GregorianCalendar(), new Barcode("123456789012"), "hellmesaof",
				new Amount(Unit.count, 13), 0, 2);
		
		assertTrue (p1.equals(p1));
		assertTrue (p1.equals(p2));
		assertFalse(p1.equals(p3));
		assertTrue (p1.equals(p3) == false);
		assertTrue (p2.equals(p3) == false);
		assertTrue (p2.equals(p4));
	}
	
}
